package com.orbbec.orbbecsdkexamples.utils;

import android.util.Log;

import com.orbbec.obsensor.DepthFrame;
import com.orbbec.obsensor.Format;
import com.orbbec.obsensor.Frame;
import com.orbbec.obsensor.FrameType;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

/**
 * @Author： LJH
 * @Time： 2024/6/27
 * @description：
 */
public class FrameConverter {

    /**
     * 将深度视图frame转成Mat
     * @param frame
     * @return
     */
    public static Mat frame2mat(DepthFrame frame) {
        if (frame == null || frame.getDataSize() < 1024) {
            return new Mat();
        }

        FrameType frameType = frame.getStreamType();
        Format frameFormat = frame.getFormat();

        int frameHeight = frame.getHeight();
        int frameWidth = frame.getWidth();

        // Get data and render
        byte[] frameData = new byte[frame.getDataSize()];
        frame.getData(frameData);
        Log.d("TAG","frameType:"+frameType.name()+", frameFormat:"+frameFormat.name()+",size:"+frameData.length);


        Mat resultMat = new Mat();
        if (frameType == FrameType.COLOR) {
            // Color image
            if (frameFormat == Format.MJPG) {
                Mat rawMat = new MatOfByte(frameData);
                resultMat = Imgcodecs.imdecode(rawMat, Imgcodecs.IMREAD_COLOR);
            } else if (frameFormat == Format.NV21) {
                Mat rawMat = new Mat(frameHeight * 3 / 2, frameWidth, CvType.CV_8UC1);
                rawMat.put(0, 0, frameData);
                Imgproc.cvtColor(rawMat, resultMat, Imgproc.COLOR_YUV2BGR_NV21);
            } else if (frameFormat == Format.YUYV || frameFormat == Format.YUY2) {
                Mat rawMat = new Mat(frameHeight, frameWidth, CvType.CV_8UC2);
                rawMat.put(0, 0, frameData);
                Imgproc.cvtColor(rawMat, resultMat, Imgproc.COLOR_YUV2BGR_YUY2);
            } else if (frameFormat == Format.RGB888) {
                Mat rawMat = new Mat(frameHeight, frameWidth, CvType.CV_8UC3);
                rawMat.put(0, 0, frameData);
                Imgproc.cvtColor(rawMat, resultMat, Imgproc.COLOR_RGB2BGR);
            } else if (frameFormat == Format.UYVY) {
                Mat rawMat = new Mat(frameHeight, frameWidth, CvType.CV_8UC2);
                rawMat.put(0, 0, frameData);
                Imgproc.cvtColor(rawMat, resultMat, Imgproc.COLOR_YUV2BGR_UYVY);
            }
        } else if (frameFormat == Format.Y16 || frameFormat == Format.YUYV || frameFormat == Format.YUY2) {
            // IR or depth image
//            Mat rawMat = new Mat(frameHeight, frameWidth, CvType.CV_16UC1);
            Mat rawMat = new Mat(frameHeight, frameWidth, CvType.CV_8UC1);
            rawMat.put(0, 0, frameData);
            double scale = 1 / Math.pow(2, frame.getPixelAvailableBitSize() - (frameType == FrameType.DEPTH ? 10 : 8));
            rawMat.convertTo(resultMat, CvType.CV_8UC1, scale);
        } else if (frameType == FrameType.IR) {
            // IR image
            if (frameFormat == Format.Y8) {
                resultMat = new Mat(frameHeight, frameWidth, CvType.CV_8UC1);
                resultMat.put(0, 0, frameData);
            } else if (frameFormat == Format.MJPG) {
                Mat rawMat = new MatOfByte(frameData);
                resultMat = Imgcodecs.imdecode(rawMat, Imgcodecs.IMREAD_GRAYSCALE);
            }
        }
        return resultMat;
    }

    /**
     * 计算填充率
     * @param depthImage
     * @return
     */
    public static double calculateFillRate(Mat depthImage) {
        int rows = depthImage.rows();
        int cols = depthImage.cols();
        int totalPixels = rows * cols;
        int validPixels = 0;

        // 遍历深度图像素并统计有效值
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                double[] pixel = depthImage.get(i, j);
                if (pixel[0] > 0) { // 假设0表示无效深度值
                    validPixels++;
                }
            }
        }

        // 计算填充率
        return (double) validPixels / totalPixels;
    }
}
